import 'dart:core';
import 'dart:typed_data';

import 'crc_utils.dart';

Uint8List byteArrayOf(List<int> data) {
  return Uint8List.fromList(data);
}

extension ByteArrayExtensions on List<int> {
  Uint8List toByteArray() => Uint8List.fromList(this);
}

extension ByteArrayIterableExtensions on Iterable<int> {
  Uint8List toByteArray() => Uint8List.fromList(toList());
}

extension HexExtensions on List<int> {
  /// crc8
  int get CRC8 => CrcUtils.CRC8(this, 0, this.length);

  int get CRC8_DARC => CrcUtils.CRC8_DARC(this, 0, this.length);

  int get CRC8_ITU => CrcUtils.CRC8_ITU(this, 0, this.length);

  int get CRC8_MAXIM => CrcUtils.CRC8_MAXIM(this, 0, this.length);

  int get CRC8_ROHC => CrcUtils.CRC8_ROHC(this, 0, this.length);

  /// crc16
  int get CRC16_CCITT_FALSE => CrcUtils.CRC16_CCITT_FALSE(this, 0);

  int get CRC16_CCITT => CrcUtils.CRC16_CCITT(this, 0, this.length);

  int get CRC16_DECT_R => CrcUtils.CRC16_DECT_R(this, 0, this.length);

  int get CRC16_DECT_X => CrcUtils.CRC16_DECT_X(this, 0, this.length);

  int get CRC16_DNP => CrcUtils.CRC16_DNP(this, 0, this.length);

  int get CRC16_GENIBUS => CrcUtils.CRC16_GENIBUS(this, 0, this.length);

  int get CRC16_IBM => CrcUtils.CRC16_IBM(this, 0, this.length);

  int get CRC16_MAXIM => CrcUtils.CRC16_MAXIM(this, 0, this.length);

  int get CRC16_MODBUS => CrcUtils.CRC16_MODBUS(this, 0, this.length);

  int get CRC16_USB => CrcUtils.CRC16_USB(this, 0, this.length);

  int get CRC16_X25 => CrcUtils.CRC16_X25(this, 0, this.length);

  int get CRC16_XMODEM => CrcUtils.CRC16_XMODEM(this, 0, this.length);

  /// crc32
  int get CRC32 => CrcUtils.CRC32(this, 0, this.length);

  int get CRC32_B => CrcUtils.CRC32_B(this, 0, this.length);

  int get CRC32_C => CrcUtils.CRC32_C(this, 0, this.length);

  int get CRC32_D => CrcUtils.CRC32_D(this, 0, this.length);

  int get CRC32_POSIX => CrcUtils.CRC32_POSIX(this, 0, this.length);

  int get CRC32_MPEG_2 => CrcUtils.CRC32_MPEG_2(this, 0, this.length);

  /// ByteArray -> 16进制字符串
  String get toHexStr => HexUtils.bytesToHexString(this);

  /// ByteArray -> 16进制字符串  空格拼接
  String get toHexStrSpace => HexUtils.bytesToHexString(this, " ");

  /// ByteArray -> Int
  int get byteToInt => HexUtils.byteToInt(this);

  /// ByteArray -> Int
  int get byteToIntLE => HexUtils.byteToInt(this, reversed: false);

  /// ByteArray -> Uint
  int get byteToUIntLE => HexUtils.byteToUInt(this, reversed: false);

  /// ByteArray -> Uint
  int get byteToUIntBE => HexUtils.byteToUInt(this, reversed: true);

  /// ByteArray -> ASCII字符串
  String get byteToASCIIStr => HexUtils.byteToASCIIStr(this, reversed: false, isSub00: false, isRemoveControl: false);

  /// 删除00和后续
  String get byteToASCIIStrSub00 => HexUtils.byteToASCIIStr(this, reversed: false, isSub00: true, isRemoveControl: false);

  /// 删除控制字符和 00和后续
  String get byteToASCIIStrDelCtrlOr00 => HexUtils.byteToASCIIStr(this, reversed: false, isSub00: true, isRemoveControl: true);

  /// 移除控制字符
  String get byteToASCIIStrDelCtrl => HexUtils.byteToASCIIStr(this, reversed: false, isSub00: false, isRemoveControl: true);
}

extension StringExtensions on String {
  /// 字符串转换成字节数组
  Uint8List get hexToBytes => HexUtils.hexStr2Bytes(this);
}

extension IntExtensions on int {
  /// 将int转化成byte[]
  Uint8List toByteArray({int size = -1, bool isReversed = true}) => HexUtils.intToBytes(this, size: size, isReversed: isReversed);

  /// 0xffff 为4个字节和2个字节的分界线
  Uint8List toByteArray2Or4([bool isReversed = true]) => HexUtils.intToBytes2Or4(this, isReversed: isReversed);

  Uint8List toByteArray4Or8([bool isReversed = true]) => HexUtils.longToBytes4Or8(toInt(), isReversed: isReversed);

  /// Int -> 16进制字符串
  String get toHexStr => toByteArray2Or4(false).toHexStr;
}

extension LongExtensions on int {
  /// 将long转化成byte[]
  Uint8List toByteArray4Or8([bool isReversed = true]) => HexUtils.longToBytes4Or8(this, isReversed: isReversed);

  /// Long -> 16进制字符串
  String get toHexStr4Or8 => toByteArray4Or8(false).toHexStr;
}

class HexUtils {
  HexUtils._();

  /// 十六进制String转换成Byte[]
  static Uint8List hexStr2Bytes(String? str) {
    if (str == null || str.isEmpty) {
      return Uint8List(0);
    }
    // 替换空格
    str = str.replaceAll(" ", "");
    final byteArray = Uint8List(str.length ~/ 2);
    for (int i = 0; i < byteArray.length; i++) {
      final subStr = str.substring(2 * i, 2 * i + 2);
      byteArray[i] = int.parse(subStr, radix: 16).toUnsigned(8);
    }
    return byteArray;
  }

  /// 将字节数组转换为16进制字符串
  static String bytesToHexString(List<int>? src, [String? joint]) {
    if (src == null || src.isEmpty) {
      return "";
    }
    final b = StringBuffer();
    for (final element in src) {
      var hex = element.toRadixString(16).padLeft(2, '0');
      b.write(hex);
      if (joint != null) {
        b.write(joint);
      }
    }
    return b.toString();
  }

  /// 将int转化成byte[]
  static Uint8List intToBytes(int res, {int size = -1, bool isReversed = true}) {
    if (size <= 0 || size > 4) {
      size = res > 0xFFFFFF
          ? 4
          : res > 0xFFFF
              ? 3
              : res > 0xFF
                  ? 2
                  : 1;
    }
    final targets = Uint8List(size);
    if (size >= 1) {
      targets[0] = (res & 0xff).toUnsigned(8); // 最低位
    }
    if (size >= 2) {
      targets[1] = ((res >> 8) & 0xff).toUnsigned(8); // 次低位
    }
    if (size >= 3) {
      targets[2] = ((res >> 16) & 0xff).toUnsigned(8); // 次高位
    }
    if (size >= 4) {
      targets[3] = ((res >>> 24) & 0xff).toUnsigned(8); // 最高位,无符号右移。
    }
    if (!isReversed) {
      targets.setAll(0, targets.reversed.toList());
    }
    return targets;
  }

  /// int 转 ByteArray  4字节和2字节
  static Uint8List intToBytes2Or4(int res, {bool isReversed = true}) {
    final targets = Uint8List(res > 0xFFFF ? 4 : 2);
    targets[0] = (res & 0xff).toUnsigned(8); // 最低位
    targets[1] = ((res >> 8) & 0xff).toUnsigned(8); // 次低位
    if (targets.length > 2) {
      targets[2] = ((res >> 16) & 0xff).toUnsigned(8); // 次高位
      targets[3] = ((res >>> 24) & 0xff).toUnsigned(8); // 最高位,无符号右移。
    }
    if (!isReversed) {
      targets.setAll(0, targets.reversed.toList());
    }
    return targets;
  }

  /// long 转 ByteArray  8字节和4字节
  static Uint8List longToBytes4Or8(int res, {bool isReversed = true}) {
    final targets = Uint8List(res > 0xFFFFFFFF ? 8 : 4);
    targets[0] = (res & 0xff).toUnsigned(8); // 最低位
    targets[1] = ((res >> 8) & 0xff).toUnsigned(8); // 次低位
    targets[2] = ((res >> 16) & 0xff).toUnsigned(8); // 次高位
    targets[3] = ((res >> 24) & 0xff).toUnsigned(8); // 最高位
    if (targets.length > 4) {
      targets[4] = ((res >> 32) & 0xff).toUnsigned(8); // 次高位
      targets[5] = ((res >> 40) & 0xff).toUnsigned(8); // 最高位
      targets[6] = ((res >> 48) & 0xff).toUnsigned(8); // 最高位
      targets[7] = ((res >>> 56) & 0xff).toUnsigned(8); // 最高位
    }
    if (!isReversed) {
      targets.setAll(0, targets.reversed.toList());
    }
    return targets;
  }

  /// 将byte[]转化成int
  static int byteToInt(List<int> res, {bool reversed = true}) {
    res = reversed ? Uint8List.fromList(res.reversed.toList()) : res;
    return (res.isNotEmpty ? res[0] & 0xff : 0) | (res.length > 1 ? (res[1] & 0xff) << 8 : 0) | (res.length > 2 ? (res[2] & 0xff) << 16 : 0) | (res.length > 3 ? (res[3] & 0xff) << 24 : 0);
  }

  /// 将byte[]转化成uint
  static int byteToUInt(List<int> res, {bool reversed = true}) {
    res = reversed ? Uint8List.fromList(res.reversed.toList()) : res;
    return (res.isNotEmpty ? res[0] & 0xff : 0) | (res.length > 1 ? (res[1] & 0xff) << 8 : 0) | (res.length > 2 ? (res[2] & 0xff) << 16 : 0) | (res.length > 3 ? (res[3] & 0xff) << 24 : 0);
  }

  /// 将byte[]转化成ASCII字符串
  static String byteToASCIIStr(List<int> res, {bool reversed = true, bool isSub00 = false, bool isRemoveControl = false}) {
    res = reversed ? Uint8List.fromList(res.reversed.toList()) : res;
    final result = StringBuffer();
    for (final it in res) {
      if (isSub00 && it == 0) break;
      if (isRemoveControl && (it < 32 || it > 126)) continue;
      result.write(String.fromCharCode(it));
    }
    return result.toString();
  }
}
